home *** CD-ROM | disk | FTP | other *** search
/ SGI Hot Mix 17 / Hot Mix 17.iso / HM17_SGI / research / lib / cw_bgroup.pro < prev    next >
Text File  |  1997-07-08  |  12KB  |  341 lines

  1. ; $Id: cw_bgroup.pro,v 1.18 1997/01/27 18:15:44 lubos Exp $
  2. ;
  3. ; Copyright (c) 1992-1997, Research Systems, Inc.  All rights reserved.
  4. ;    Unauthorized reproduction prohibited.
  5. ;+
  6. ; NAME:
  7. ;    CW_BGROUP
  8. ;
  9. ; PURPOSE:
  10. ;    CW_BGROUP is a compound widget that simplifies creating
  11. ;    a base of buttons. It handles the details of creating the
  12. ;    proper base (standard, exclusive, or non-exclusive) and filling
  13. ;    in the desired buttons. Events for the individual buttons are
  14. ;    handled transparently, and a CW_BGROUP event returned. This
  15. ;    event can return any one of the following:
  16. ;        - The Index of the button within the base.
  17. ;        - The widget ID of the button.
  18. ;        - The name of the button.
  19. ;        - An arbitrary value taken from an array of User values.
  20. ;
  21. ; CATEGORY:
  22. ;    Compound widgets.
  23. ;
  24. ; CALLING SEQUENCE:
  25. ;        Widget = CW_BGROUP(Parent, Names)
  26. ;
  27. ;    To get or set the value of a CW_BGROUP, use the GET_VALUE and
  28. ;    SET_VALUE keywords to WIDGET_CONTROL. The value of a CW_BGROUP
  29. ;    is:
  30. ;
  31. ;        -----------------------------------------------
  32. ;        Type        Value
  33. ;        -----------------------------------------------
  34. ;        normal        None
  35. ;        exclusive       Index of currently set button
  36. ;        non-exclusive    Vector indicating the position
  37. ;                of each button (1-set, 0-unset)
  38. ;        -----------------------------------------------
  39. ;
  40. ;
  41. ; INPUTS:
  42. ;       Parent:        The ID of the parent widget.
  43. ;    Names:        A string array, containing one string per button,
  44. ;            giving the name of each button.
  45. ;
  46. ; KEYWORD PARAMETERS:
  47. ;
  48. ;    BUTTON_UVALUE:    An array of user values to be associated with
  49. ;            each button and returned in the event structure.
  50. ;    COLUMN:        Buttons will be arranged in the number of columns
  51. ;            specified by this keyword.
  52. ;    EVENT_FUNCT:    The name of an optional user-supplied event function 
  53. ;            for buttons. This function is called with the return
  54. ;            value structure whenever a button is pressed, and 
  55. ;            follows the conventions for user-written event
  56. ;            functions.
  57. ;    EXCLUSIVE:    Buttons will be placed in an exclusive base, with
  58. ;            only one button allowed to be selected at a time.
  59. ;    FONT:        The name of the font to be used for the button
  60. ;            titles. If this keyword is not specified, the default
  61. ;            font is used.
  62. ;    FRAME:        Specifies the width of the frame to be drawn around
  63. ;            the base.
  64. ;    IDS:        A named variable into which the button IDs will be
  65. ;            stored, as a longword vector.
  66. ;    LABEL_LEFT:    Creates a text label to the left of the buttons.
  67. ;    LABEL_TOP:    Creates a text label above the buttons.
  68. ;    MAP:        If set, the base will be mapped when the widget
  69. ;            is realized (the default).
  70. ;    NONEXCLUSIVE:    Buttons will be placed in an non-exclusive base.
  71. ;            The buttons will be independent.
  72. ;    NO_RELEASE:    If set, button release events will not be returned.
  73. ;    RETURN_ID:    If set, the VALUE field of returned events will be
  74. ;            the widget ID of the button.
  75. ;    RETURN_INDEX:    If set, the VALUE field of returned events will be
  76. ;            the zero-based index of the button within the base.
  77. ;            THIS IS THE DEFAULT.
  78. ;    RETURN_NAME:    If set, the VALUE field of returned events will be
  79. ;            the name of the button within the base.
  80. ;    ROW:        Buttons will be arranged in the number of rows
  81. ;            specified by this keyword.
  82. ;    SCROLL:        If set, the base will include scroll bars to allow
  83. ;            viewing a large base through a smaller viewport.
  84. ;    SET_VALUE:    The initial value of the buttons. This is equivalent
  85. ;            to the later statement:
  86. ;
  87. ;            WIDGET_CONTROL, widget, set_value=value
  88. ;
  89. ;    SPACE:        The space, in pixels, to be left around the edges
  90. ;            of a row or column major base. This keyword is
  91. ;            ignored if EXCLUSIVE or NONEXCLUSIVE are specified.
  92. ;    UVALUE:        The user value to be associated with the widget.
  93. ;    XOFFSET:    The X offset of the widget relative to its parent.
  94. ;    XPAD:        The horizontal space, in pixels, between children
  95. ;            of a row or column major base. Ignored if EXCLUSIVE
  96. ;            or NONEXCLUSIVE are specified.
  97. ;    XSIZE:        The width of the base. 
  98. ;    X_SCROLL_SIZE:    The width of the viewport if SCROLL is specified.
  99. ;    YOFFSET:    The Y offset of the widget relative to its parent.
  100. ;    YPAD:        The vertical space, in pixels, between children of
  101. ;            a row or column major base. Ignored if EXCLUSIVE
  102. ;            or NONEXCLUSIVE are specified.
  103. ;    YSIZE:        The height of the base. 
  104. ;    Y_SCROLL_SIZE:    The height of the viewport if SCROLL is specified.
  105. ;
  106. ; OUTPUTS:
  107. ;       The ID of the created widget is returned.
  108. ;
  109. ; SIDE EFFECTS:
  110. ;    This widget generates event structures with the following definition:
  111. ;
  112. ;        event = { ID:0L, TOP:0L, HANDLER:0L, SELECT:0, VALUE:0 }
  113. ;
  114. ;    The SELECT field is passed through from the button event. VALUE is
  115. ;    either the INDEX, ID, NAME, or BUTTON_UVALUE of the button,
  116. ;    depending on how the widget was created.
  117. ;
  118. ; RESTRICTIONS:
  119. ;    Only buttons with textual names are handled by this widget.
  120. ;    Bitmaps are not understood.
  121. ;
  122. ; MODIFICATION HISTORY:
  123. ;    15 June 1992, AB
  124. ;    7 April 1993, AB, Removed state caching.
  125. ;    6 Oct. 1994, KDB, Font keyword is not applied to the label.
  126. ;       10 FEB 1995, DJC  fixed bad bug in event procedure, getting
  127. ;                         id of stash widget.
  128. ;    11 April 1995, AB Removed Motif special cases.
  129. ;-
  130.  
  131.  
  132. pro CW_BGROUP_SETV, id, value
  133.  
  134.   ON_ERROR, 2                        ;return to caller
  135.  
  136.   stash = WIDGET_INFO(id, /CHILD)
  137.   WIDGET_CONTROL, stash, GET_UVALUE=state, /NO_COPY
  138.  
  139.   case state.type of
  140.     0: message,'unable to set plain button group value'
  141.     1: begin
  142.       WIDGET_CONTROL, SET_BUTTON=0, state.ids[state.excl_pos]
  143.       state.excl_pos = value
  144.       WIDGET_CONTROL, /SET_BUTTON, state.ids[value]
  145.     end
  146.     2: begin
  147.       n = n_elements(value)-1
  148.       for i = 0, n do begin
  149.         state.nonexcl_curpos[i] = value[i]
  150.         WIDGET_CONTROL, state.ids[i], SET_BUTTON=value[i]
  151.       endfor
  152.     end
  153.   endcase
  154.  
  155.   WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
  156. end
  157.  
  158.  
  159.  
  160. function CW_BGROUP_GETV, id, value
  161.  
  162.   ON_ERROR, 2                        ;return to caller
  163.  
  164.   stash = WIDGET_INFO(id, /CHILD)
  165.   WIDGET_CONTROL, stash, GET_UVALUE=state, /NO_COPY
  166.  
  167.   case state.type of
  168.     0: message,'unable to get plain button group value'
  169.     1: ret = state.excl_pos
  170.     2: ret = state.nonexcl_curpos
  171.   endcase
  172.  
  173.   WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
  174.  
  175.   return, ret
  176.  
  177. end
  178.  
  179.  
  180.  
  181. function CW_BGROUP_EVENT, ev
  182.   WIDGET_CONTROL, ev.handler, GET_UVALUE=stash
  183.   WIDGET_CONTROL, stash, GET_UVALUE=state, /NO_COPY
  184.   WIDGET_CONTROL, ev.id, get_uvalue=uvalue
  185.  
  186.   ret = 1            ;Assume we return a struct
  187.   case state.type of
  188.     0:
  189.     1: if (ev.select eq 1) then begin
  190.       state.excl_pos = uvalue
  191.     ENDIF else begin
  192.       if (state.no_release ne 0) then ret = 0
  193.     ENDELSE
  194.     2: begin
  195.       ; Keep track of the current state
  196.       state.nonexcl_curpos[uvalue] = ev.select
  197.           if (state.no_release ne 0) and (ev.select eq 0) then ret = 0
  198.     end
  199.   endcase
  200.  
  201.   if ret then begin        ;Return a struct?
  202.       ret = { ID:state.base, TOP:ev.top, HANDLER:0L, SELECT:ev.select, $
  203.            VALUE:state.ret_arr[uvalue] }
  204.       efun = state.efun
  205.       WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
  206.       if efun ne '' then return, CALL_FUNCTION(efun, ret) $
  207.       else return, ret
  208.   endif else begin        ;Trash the event
  209.       WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
  210.       return, 0
  211.   endelse
  212. end
  213.  
  214.  
  215.  
  216.  
  217.  
  218.  
  219.  
  220. function CW_BGROUP, parent, names, $
  221.     BUTTON_UVALUE = button_uvalue, COLUMN=column, EVENT_FUNCT = efun, $
  222.     EXCLUSIVE=excl, FONT=font, FRAME=frame, IDS=ids, LABEL_TOP=label_top, $
  223.     LABEL_LEFT=label_left, MAP=map, $
  224.     NONEXCLUSIVE=nonexcl, NO_RELEASE=no_release, RETURN_ID=return_id, $
  225.     RETURN_INDEX=return_index, RETURN_NAME=return_name, $
  226.     ROW=row, SCROLL=scroll, SET_VALUE=sval, SPACE=space, UVALUE=uvalue, $
  227.     XOFFSET=xoffset, XPAD=xpad, XSIZE=xsize, X_SCROLL_SIZE=x_scroll_size,$
  228.     YOFFSET=yoffset, YPAD=ypad, YSIZE=ysize, Y_SCROLL_SIZE=y_scroll_size
  229.  
  230.  
  231.   IF (N_PARAMS() ne 2) THEN MESSAGE, 'Incorrect number of arguments'
  232.  
  233.   ON_ERROR, 2                        ;return to caller
  234.  
  235.   ; Set default values for the keywords
  236.   version = WIDGET_INFO(/version)
  237.   if (version.toolkit eq 'OLIT') then def_space_pad = 4 else def_space_pad = 3
  238.   IF (N_ELEMENTS(column) eq 0)         then column = 0
  239.   IF (N_ELEMENTS(excl) eq 0)         then excl = 0
  240.   IF (N_ELEMENTS(frame) eq 0)        then frame = 0
  241.   IF (N_ELEMENTS(map) eq 0)        then map=1
  242.   IF (N_ELEMENTS(nonexcl) eq 0)        then nonexcl = 0
  243.   IF (N_ELEMENTS(no_release) eq 0)    then no_release = 0
  244.   IF (N_ELEMENTS(row) eq 0)        then row = 0
  245.   IF (N_ELEMENTS(scroll) eq 0)        then scroll = 0
  246.   IF (N_ELEMENTS(space) eq 0)        then space = def_space_pad
  247.   IF (N_ELEMENTS(uvalue) eq 0)        then uvalue = 0
  248.   IF (N_ELEMENTS(xoffset) eq 0)        then xoffset=0
  249.   IF (N_ELEMENTS(xpad) eq 0)        then xpad = def_space_pad
  250.   IF (N_ELEMENTS(xsize) eq 0)        then xsize = 0
  251.   IF (N_ELEMENTS(x_scroll_size) eq 0)    then x_scroll_size = 0
  252.   IF (N_ELEMENTS(yoffset) eq 0)        then yoffset=0
  253.   IF (N_ELEMENTS(ypad) eq 0)        then ypad = def_space_pad
  254.   IF (N_ELEMENTS(ysize) eq 0)        then ysize = 0
  255.   IF (N_ELEMENTS(y_scroll_size) eq 0)    then y_scroll_size = 0
  256.   
  257.  
  258.  
  259.  
  260.   top_base = 0L
  261.   if (n_elements(label_top) ne 0) then begin
  262.     next_base = WIDGET_BASE(parent, XOFFSET=xoffset, YOFFSET=yoffset, /COLUMN)
  263.     if(keyword_set(font))then $
  264.        junk = WIDGET_LABEL(next_base, value=label_top,font=font) $
  265.     else    junk = WIDGET_LABEL(next_base, value=label_top)
  266.     top_base = next_base
  267.   endif else next_base = parent
  268.   if (n_elements(label_left) ne 0) then begin
  269.     next_base = WIDGET_BASE(next_base, XOFFSET=xoffset, YOFFSET=yoffset, /ROW)
  270.     if(keyword_set(font))then $
  271.        junk = WIDGET_LABEL(next_base, value=label_left, font=font) $
  272.     else junk = WIDGET_LABEL(next_base, value=label_left)
  273.     if (top_base eq 0L) then top_base = next_base
  274.   endif
  275.   ; We need some kind of outer base to hold the users UVALUE
  276.   if (top_base eq 0L) then begin
  277.     top_base = WIDGET_BASE(parent, XOFFSET=xoffset, YOFFSET=yoffset)
  278.     next_base = top_base
  279.   endif
  280.   If (top_base EQ next_base) THEN $
  281.      next_base = WIDGET_BASE(top_base, Xpad=1, Ypad=1, Space=1)
  282.  
  283.   ; Set top level base attributes
  284.   WIDGET_CONTROL, top_base, MAP=map, $
  285.     FUNC_GET_VALUE='CW_BGROUP_GETV', PRO_SET_VALUE='CW_BGROUP_SETV', $
  286.     SET_UVALUE=uvalue
  287.  
  288.   ; The actual button holding base
  289.   base = WIDGET_BASE(next_base, COLUMN=column, EXCLUSIVE=excl, FRAME=frame, $
  290.     NONEXCLUSIVE=nonexcl, ROW=row, SCROLL=scroll, SPACE=space, $
  291.     XPAD=xpad, XSIZE=xsize, X_SCROLL_SIZE=x_scroll_size, $
  292.     YPAD=ypad, YSIZE=ysize, Y_SCROLL_SIZE=y_scroll_size, $
  293.     EVENT_FUNC='CW_BGROUP_EVENT', $
  294.     UVALUE=WIDGET_INFO(top_base, /child))
  295.  
  296.  
  297.   n = n_elements(names)
  298.   ids = lonarr(n)
  299.   for i = 0, n-1 do begin
  300.     if (n_elements(font) eq 0) then begin
  301.       ids[i] = WIDGET_BUTTON(base, value=names[i], UVALUE=i)
  302.     endif else begin
  303.       ids[i] = WIDGET_BUTTON(base, value=names[i], FONT=font, UVALUE=i)
  304.     endelse
  305.   endfor
  306.  
  307.   ; Keep the state info in the real (inner) base UVALUE.
  308.   ; Pick an event value type:
  309.   ;    0 - Return ID
  310.   ;    1 - Return INDEX
  311.   ;    2 - Return NAME
  312.   ret_type = 1
  313.   if KEYWORD_SET(RETURN_ID) then ret_type = 0
  314.   if KEYWORD_SET(RETURN_NAME) then ret_type = 2
  315.   if KEYWORD_SET(BUTTON_UVALUE) then ret_type = 3
  316.     case ret_type of
  317.       0: ret_arr = ids
  318.       1: ret_arr = indgen(n)
  319.       2: ret_arr = names
  320.       3: ret_arr = button_uvalue
  321.     endcase
  322.   type = 0
  323.   if (excl ne 0) then type = 1
  324.  
  325.   if (nonexcl ne 0) then type = 2
  326.   if n_elements(efun) le 0 then efun = ''
  327.   state = { type:type, $    ; 0-Standard, 1-Exclusive, 2-Non-exclusive
  328.         base: top_base, $    ; cw_bgroup base...
  329.         ret_arr:ret_arr, $    ; Vector of event values
  330.         efun : efun, $    ; Name of event fcn
  331.         nonexcl_curpos:intarr(n), $    ; If non-exclus, tracks state
  332.         excl_pos:0, $            ; If exclusive, current button
  333.         ids:ids, $            ; Ids of buttons
  334.         no_release:no_release }
  335.   WIDGET_CONTROL, WIDGET_INFO(top_base, /CHILD), SET_UVALUE=state, /NO_COPY
  336.  
  337.   if (n_elements(sval) ne 0) then CW_BGROUP_SETV, top_base, sval
  338.  
  339.   return, top_base
  340. END
  341.